package jduck.ui;

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import javax.swing.UIManager;

import net.miginfocom.swing.MigLayout;

import org.eclipse.wb.swing.FocusTraversalOnArray;
import java.awt.event.InputMethodListener;
import java.awt.event.InputMethodEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.sql.Savepoint;
import java.util.prefs.Preferences;
import java.util.prefs.PreferencesFactory;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JTextField;
import javax.swing.JTextArea;
import java.awt.Dimension;
import javax.swing.border.TitledBorder;
import java.awt.Font;
import javax.swing.border.BevelBorder;

public class jDuck {

	final private JFrame frmJducky;
	final Preferences prefs = Preferences.userNodeForPackage(jDuck.class);
	static final String PREF_SCRIPT = "script";
	static final String PREF_INTERVAL_SEL = "intervalSel";
	static final String PREF_TOT_TIME_SEL = "totalTimeSel";
	static final String PREF_RAND_OFFSET_SEL = "randomOffsetSel";

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
					final jDuck window = new jDuck();
					window.frmJducky.setIconImage(Toolkit.getDefaultToolkit().getImage(
							jDuck.class.getResource("/jduck/ui/main.png")));
					window.frmJducky.addWindowListener(new WindowListener() {

						@Override
						public void windowOpened(WindowEvent arg0) {
							// TODO Auto-generated method stub

						}

						@Override
						public void windowIconified(WindowEvent arg0) {
							// TODO Auto-generated method stub

						}

						@Override
						public void windowDeiconified(WindowEvent arg0) {
							// TODO Auto-generated method stub

						}

						@Override
						public void windowDeactivated(WindowEvent arg0) {
							// TODO Auto-generated method stub

						}

						@Override
						public void windowClosing(WindowEvent arg0) {
							window.savePrefs();
//							if ( window.clicker!=null ) {
//								if ( window.clicker.isAlive() )
//									System.err.println("click still alive");
//							}
							window.killClicker();
						}

						@Override
						public void windowClosed(WindowEvent arg0) {
							// TODO Auto-generated method stub

						}

						@Override
						public void windowActivated(WindowEvent arg0) {
							// TODO Auto-generated method stub

						}
					});
					window.frmJducky.setVisible(true);

				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public jDuck() {
		frmJducky = new JFrame();
		frmJducky.setMinimumSize(new Dimension(200, 300));
		frmJducky.setPreferredSize(new Dimension(200, 300));
		initialize();
	}

	public String previousStatus = "";
	final JComboBox cbTime = new JComboBox();
	final JComboBox cbRanAdd = new JComboBox();
	final JComboBox cbMinInterval = new JComboBox();
	final JLabel lblStatus = new JLabel("");
	final JLabel lblCount = new JLabel("Total time (minutes)");
	final JLabel lblRandomAdd = new JLabel("Random add");
	final JButton btnStart = new JButton("Start");
	private final JTextArea textScript = new JTextArea();
	private final JScrollPane scrollPane = new JScrollPane(textScript);
	Clicker clicker = null;

	/**
	 * Initialize the contents of the frame.
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private void initialize() {
		frmJducky.setIconImage(Toolkit.getDefaultToolkit().getImage(jDuck.class.getResource("/jduck/ui/main.png")));
		frmJducky.setTitle("jDucky");
		frmJducky.setBounds(100, 100, 193, 274);
		frmJducky.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		frmJducky.getContentPane().setLayout(new MigLayout("", "[grow][grow 50,fill]", "[][][][][][grow,fill]"));

		JLabel lblInterval = new JLabel("Min Interval");
		frmJducky.getContentPane().add(lblInterval, "cell 0 0,alignx trailing");
		cbTime.setMinimumSize(new Dimension(14, 20));
		cbTime.setModel(new DefaultComboBoxModel(new String[] { "0", "1", "2", "5", "10", "15", "30", "45", "60", "90",
				"120", "180", "240", "300", "360", "720", "1440", "2880" }));
		cbTime.setSelectedIndex(prefs.getInt(PREF_TOT_TIME_SEL, 8));
		cbMinInterval.setMinimumSize(new Dimension(14, 20));
		cbMinInterval.setModel(new DefaultComboBoxModel(new String[] { "2", "5", "15", "30", "60", "120", "130", "300",
				"600", "1800", "3600" }));
		cbMinInterval.setSelectedIndex(prefs.getInt(PREF_INTERVAL_SEL, 4));
		cbRanAdd.setMinimumSize(new Dimension(14, 20));

		cbRanAdd.setModel(new DefaultComboBoxModel(new String[] { "0", "5", "10", "15", "30", "60", "120", "300",
				"900" }));
		cbRanAdd.setSelectedIndex(prefs.getInt(PREF_RAND_OFFSET_SEL, 4));
		frmJducky.getContentPane().add(cbRanAdd, "cell 1 1,growx");

		cbMinInterval.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				long interval = Long.parseLong(cbMinInterval.getSelectedItem().toString()) * 1000L;
				long time = Long.parseLong(cbTime.getSelectedItem().toString()) * 60000L;
				lblStatus.setText("<html>Run for: " + Clicker.longSpanToStringShort(time) + "<br>Click every "
						+ Clicker.longSpanToStringShort(interval));
			}
		});
		cbTime.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				long interval = Long.parseLong(cbMinInterval.getSelectedItem().toString()) * 1000L;
				long time = Long.parseLong(cbTime.getSelectedItem().toString()) * 60000L;

				lblStatus.setText("<html>Run for: " + Clicker.longSpanToStringShort(time) + "<br>Click every "
						+ Clicker.longSpanToStringShort(interval));
			}
		});

		frmJducky.getContentPane().add(cbMinInterval, "flowx,cell 1 0,growx");

		frmJducky.getContentPane().add(lblRandomAdd, "cell 0 1,alignx right");

		frmJducky.getContentPane().add(lblCount, "cell 0 2,alignx trailing");

		frmJducky.getContentPane().add(cbTime, "cell 1 2,growx");
		btnStart.setBorder(null);
		btnStart.setMinimumSize(new Dimension(21, 23));

		frmJducky.getContentPane().add(btnStart, "cell 0 3 2 1,growx");

		btnStart.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				// store UI idea of run state in the text - why not?
				if (btnStart.getText().equalsIgnoreCase("Start")) {
					Script script = null;
					try {
						script = new Script(textScript.getText());
					} catch (Exception ex) {
						JOptionPane.showMessageDialog(null, "Script setup problem: " + ex.getMessage(), "Script error",
								JOptionPane.INFORMATION_MESSAGE);
						return;
					}

					long interval = Long.parseLong(cbMinInterval.getSelectedItem().toString()) * 1000L;
					long ranOffset = Long.parseLong(cbRanAdd.getSelectedItem().toString()) * 1000L;
					long time = Long.parseLong(cbTime.getSelectedItem().toString()) * 60000L;
					clicker = new Clicker(btnStart, lblStatus, frmJducky, interval, time, ranOffset, script);
					clicker.setDaemon(true); // so process will exit even if we do not kill this thread
					clicker.start();
					savePrefs();
					lblStatus.setText("Stop");
				} else if (clicker != null) {
					clicker.interrupt();
					try {
						clicker.join();
					} catch (InterruptedException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}

				}
			}
		});
		long interval = Long.parseLong(cbMinInterval.getSelectedItem().toString()) * 1000L;
		long time = Long.parseLong(cbTime.getSelectedItem().toString()) * 60000L;

		JRootPane jroot = frmJducky.getRootPane();
		jroot.setDefaultButton(btnStart);

		lblStatus.setHorizontalAlignment(SwingConstants.LEFT);
		frmJducky.getContentPane().add(lblStatus, "flowy,cell 0 4 2 1,growx");

		lblStatus.setText("<html>Run for: " + Clicker.longSpanToStringShort(time) + "<br>Click every "
				+ Clicker.longSpanToStringShort(interval));
		textScript.setToolTipText("Script to execute - saved in preferences on start or exit.");
		textScript.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
		textScript.setMinimumSize(new Dimension(1, 1));
		textScript.setWrapStyleWord(true);
		textScript.setTabSize(4);
		textScript.setLineWrap(true);
		textScript.setFont(new Font("Monospaced", Font.PLAIN, 12));
		textScript.setText(prefs.get(PREF_SCRIPT, "M1"));
		frmJducky.getContentPane().add(scrollPane, "cell 0 5 2 1,grow");
		frmJducky.getContentPane().setFocusTraversalPolicy(
				new FocusTraversalOnArray(new Component[] { btnStart, cbMinInterval, cbTime, cbRanAdd }));
		lblStatus.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
				long interval = Long.parseLong(cbMinInterval.getSelectedItem().toString()) * 1000L;
				long time = Long.parseLong(cbTime.getSelectedItem().toString()) * 60000L;

				lblStatus.setText("<html>Run for: " + Clicker.longSpanToStringShort(time) + "<br>Click every "
						+ Clicker.longSpanToStringShort(interval));

			}
		});

		int i = 0;
	}

	public void savePrefs() {
		prefs.put(PREF_SCRIPT, textScript.getText());
		prefs.putInt(PREF_INTERVAL_SEL, this.cbMinInterval.getSelectedIndex());
		prefs.putInt(PREF_TOT_TIME_SEL, this.cbTime.getSelectedIndex());
		prefs.putInt(PREF_RAND_OFFSET_SEL, this.cbRanAdd.getSelectedIndex());
	}

	public void killClicker() {
		try {
			if (clicker != null) {
				if (clicker.isAlive()) {
					clicker.interrupt();
					clicker.join(500L);
					if (clicker.isAlive())
						clicker.stop();
				}
				clicker = null;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			JOptionPane.showMessageDialog(null,
					"Script problem shutting down clicker thread - resorting to kill, exception: " + ex.getMessage(),
					"Click thread will not stop", JOptionPane.INFORMATION_MESSAGE);
			return;
		} finally {
			if (clicker != null)
				try {
					clicker.stop();
				} catch (Exception ex) {
					ex.printStackTrace();
					JOptionPane.showMessageDialog(
							null,
							"Script problem shutting down clicker thread - kill failing as well, exception: "
									+ ex.getMessage(), "Click thread will not stop", JOptionPane.INFORMATION_MESSAGE);
					return;
				}
		}
	}
}
